package se.webbzon.boltzmann.minigame.question;

import java.awt.Image;
import java.io.IOException;
import java.net.URL;

import se.webbzon.boltzmann.debug.Debug;
import se.webbzon.boltzmann.input.Input;
import se.webbzon.boltzmann.loader.LoaderException;
import se.webbzon.boltzmann.loader.LoaderUtility;
import se.webbzon.boltzmann.minigame.page.PageItem;
import se.webbzon.boltzmann.minigame.page.PageLayout;
import se.webbzon.boltzmann.minigame.page.PageParser;
import se.webbzon.boltzmann.minigame.page.PageText;
import se.webbzon.boltzmann.resource.Resources;
import se.webbzon.oschi01.resourceset.ResourceSet;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldcamera.WorldCameraPane;
import se.webbzon.oschi01.worldobject.WorldObject;

public class QuestionController extends WorldObject {
	
	// The 2-dimensional depth of this question controller
	private static final int depth = -2;
	
	// The image set of the dot
	private static final ResourceSet<Image> dot = 
			Resources.getImageSet("minigame_question_dot");
	
	// The front and back page of the question
	private final QuestionPage frontPage, backPage;
	
	// The selector associated with this controller
	private final QuestionSelector selector;
	
	// An array containing the result of the questions
	private int[] result;
	
	/*============================================================
	Constructors
	============================================================*/

	public QuestionController(PageLayout layout, Input input, URL url) {
		super(WorldObject.onCreate + WorldObject.onDestroy + WorldObject.onPostDraw, depth);
		result = null;
		
		// Load the questions from the provided URL
		QuestionLoader loader = new QuestionLoader();
		LoaderUtility lu = new LoaderUtility();
		lu.addLoader(loader);
		try {
			lu.loadFromXML(url);
		} catch (LoaderException e) {
			Debug.report(e);
		}
		
		// Create selector
		selector = new QuestionSelector(layout,input,loader.getQuestions());
		
		// Create parser (optional)
		final URL front = loader.getFront(), back = loader.getBack();
		PageParser parser = null;
		if (front != null || back != null) {
			parser = new PageParser();
			parser.addTag(new AlternativeTag());
			parser.addTag(new AnswerTag());
		}
		
		// Create front
		frontPage = new QuestionPage(layout, input);
		if (front == null)
			createFront(frontPage,layout);
		else try {
			for (PageItem item : parser.parse(layout, front))
				frontPage.addItem(item);
		} catch (IOException e) {
			Debug.report(e);
		}
		
		// Create back
		backPage = new QuestionPage(layout, input);
		if (back == null)
			createBack(backPage,layout);
		else try {
			for (PageItem item : parser.parse(layout, back))
				backPage.addItem(item);
		} catch (IOException e) {
			Debug.report(e);
		}
			
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Resets the question controller. **/
	public void reset() {
		WorldArea world = getWorld();
		if (world != null) try {
			// Clear current question
			QuestionPage current = selector.current();
			if (current != null && current.exists()) {
				world.destroyInstance(current);
				current.clearListeners();
			}
			
			// Clear back page
			if (backPage.exists()) {
				world.destroyInstance(backPage);
				backPage.clearListeners();
			}
			
			// Show front page
			if (!frontPage.exists())
				world.createInstance(frontPage);
			frontPage.clearListeners();
			frontPage.addListener(new QuestionListenerImpl());
			
			// Reset selector
			selector.reset();
			result = new int[selector.questions()];
		} catch (IOException e) {
			Debug.report(e);
		}
	}
	
	@Override public void onCreate(WorldArea world) {
		reset();
	}

	@Override public void onDestroy(WorldArea world) {
		if (frontPage.exists())
			world.destroyInstance(frontPage);
		else if (backPage.exists())
			world.destroyInstance(backPage);
		else if (selector.current().exists())
			world.destroyInstance(selector.current());
	}
	
	@Override public void onPostDraw(WorldArea world, WorldCameraPane hud) {
		if (result != null) {
			for (int i = 0; i < result.length; i++)
				hud.drawImage(dot.get(result[i]), 8 + 24 * i, 8);
		}
	}
	
	
	/*============================================================
	Private Methods
	============================================================*/

	/** Builds the front page. **/
	private final void createFront(QuestionPage front, PageLayout layout) {
		PageText header = new PageText(layout, "Quiz");
		header.setLevel(1);
		front.addItem(header);
		front.addItem(new PageText(layout, "20 questions will be randomly selected for this quiz. You will need at least 10 points to complete this exercise."));
		front.addItem(new AlternativeItem(layout, 1, "Start quiz!"));
		front.addItem(new AnswerItem(1));
	}
	
	/** Builds the back page. **/
	private final void createBack(QuestionPage back, PageLayout layout) {
		PageText header = new PageText(layout, "End of quiz!");
		header.setLevel(1);
		back.addItem(header);
	}
	
	/*============================================================
	Private Classes
	============================================================*/

	private final class QuestionListenerImpl implements QuestionListener {

		@Override public void onSubmit(QuestionPage page, boolean correct) {
			page.removeListener(this);
			WorldArea world = page.getWorld();
			if (world != null) {
				world.destroyInstance(page);
				if (page == selector.current())
					result[selector.question()] = correct ? 2 : 1;
				if (selector.hasNext()) {
					QuestionPage p = selector.next();
					world.createInstance(p);
					p.addListener(this);
				} else {
					world.createInstance(backPage);
					backPage.addListener(this);
				}
			}
		}
		
	}

}
